package com.ahmedmisbah.andgenplus.utils.xml;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.List;

import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

public class XMLUtil {

	public XMLUtil() {
	}

	/**
	 * Returns an DOM4J XML document given its file path
	 * 
	 * @param url
	 *            : XML file Path
	 * @return Document
	 * @throws IOException
	 * @throws DocumentException
	 */
	public Document getDocument(String url) throws IOException,
			DocumentException {
		Document ret = null;
		InputStream is = null;

		is = new FileInputStream(url);

		if (is != null) {
			SAXReader reader = new SAXReader();
			ret = reader.read(is);
		}
		return ret;
	}

	/**
	 * Returns an DOM4J XML document given its file path
	 * 
	 * @param url
	 *            XML URL
	 * @return Document
	 * @throws IOException
	 * @throws DocumentException
	 */
	public Document getDocument(URL url) throws IOException, DocumentException {
		Document ret = null;
		InputStream is = null;

		is = url.openStream();

		if (is != null) {
			SAXReader reader = new SAXReader();
			ret = reader.read(is);
		}
		return ret;
	}

	/**
	 * Returns an DOM4J XML document given its file path
	 * 
	 * @param xmlInputStream
	 *            XML URL
	 * @return Document
	 * @throws IOException
	 * @throws DocumentException
	 */
	public Document getDocument(InputStream xmlInputStream)
			throws IOException, DocumentException {
		Document ret = null;

		if (xmlInputStream != null) {
			SAXReader reader = new SAXReader();
			ret = reader.read(xmlInputStream);
		}
		return ret;
	}

	/**
	 * Returns XML root element from a given XML file
	 * 
	 * @param url
	 *            : XML file Path
	 * @return Element: Root Element
	 * @throws IOException
	 * @throws DocumentException
	 */
	public Element load(String url) throws IOException, DocumentException {
		Element ret = null;
		Document doc = getDocument(url);
		ret = doc.getRootElement();
		return ret;
	}

	/**
	 * Returns XML root element from a given XML file
	 * 
	 * @param url
	 *            : XML file Path
	 * @return Element: Root Element
	 * @throws IOException
	 * @throws DocumentException
	 */
	public Element load(URL url) throws IOException, DocumentException {
		Element ret = null;
		Document doc = getDocument(url);
		ret = doc.getRootElement();
		return ret;
	}

	/**
	 * Returns XML root element from a given XML file
	 * 
	 * @param xmlInputStream
	 * @return Element: Root Element
	 * @throws IOException
	 * @throws DocumentException
	 */
	public Element load(InputStream xmlInputStream) throws IOException,
			DocumentException {
		Element ret = null;
		Document doc = getDocument(xmlInputStream);
		ret = doc.getRootElement();
		return ret;
	}

	/**
	 * Returns a tag's attribute value given its name
	 * 
	 * @param elt
	 * @param attribute
	 * @return
	 */
	public String getAttribute(Element elt, String attribute) {
		String ret = null;
		Attribute att = elt.attribute(attribute);
		if (att != null) {
			ret = att.getValue();
		}
		return ret;
	}

	/**
	 * Returns a child xml element given its parent element
	 * 
	 * @param root
	 * @param specifier
	 * @param isXpath
	 * @return
	 */
	public Element getElement(Element root, String specifier, boolean isXpath) {
		Element ret = null;
		if (isXpath) {
			List nodes = root.selectNodes(specifier);
			if (nodes != null && nodes.size() > 0) {
				ret = (Element) nodes.get(0);
			}
		} else {
			ret = root.element(specifier);
		}
		return ret;
	}

	@SuppressWarnings("unchecked")
	public List<Element> getElements(Element root) {
		return root.elements();
	}

	public List<Element> getElements(Element root, String nodeTag) {
		return getElements(root, nodeTag, false);
	}

	@SuppressWarnings("unchecked")
	public List<Element> getElements(Element root, String specifier,
			boolean isXpath) {
		List<Element> ret = null;
		if (isXpath) {
			ret = root.selectNodes(specifier);
		} else {
			ret = root.elements(specifier);
		}
		return ret;
	}

	private StringBuilder getXMLAsString(Element element) {

		StringBuilder ret = new StringBuilder();

		ret.append("<" + element.getName());

		List<Attribute> attributes = element.attributes();

		if (attributes != null && attributes.size() > 0) {
			for (Attribute attribute : attributes) {
				ret.append(" " + attribute.getName() + "=\""
						+ attribute.getValue() + "\"");
			}
		}

		List<Element> childElements = getElements(element);

		if (childElements != null && childElements.size() > 0) {
			ret.append(">");
			for (Element childElement : childElements) {
				StringBuilder elementString = getXMLAsString(childElement);
				ret.append(elementString);
			}
			ret.append("</" + element.getName() + ">");
		} else {
			ret.append("/>");
		}

		return ret;

	}

	public String getXMLAsString(String xmlPath) throws IOException,
			DocumentException {

		Document doc = getDocument(xmlPath);
		Element rootElement = doc.getRootElement();

		String ret = getXMLAsString(rootElement).toString();

		return ret;
	}
}
